#include "Renderer.h"
#include "./Common/Utility.h"
#include "EventReceiver.h"
#include "Irrlicht/TextArea.h"
#include "CGUICodeEditor.h"
#include <iostream>
#include <sstream>
#include "RatingGUI.h"
#include "EmotionBar.h"
#include "AvgEmoGraph.h"
#include "NFData/DataMgr.h"
#include "World/World.h"
#include "Common/FileIO.h"
#include "Common/Attribute.h"

using namespace irr; 
using namespace core;
using namespace gui; 
using namespace video; 
using namespace scene; 

static char* t_boxTexturePath[] = 
{
	"./media/crate.jpg",
	"./media/crate01.jpg",
	"./media/sampleBox.jpg",
	"./media/concrete01.jpg",
	"./media/concrete02.jpg",
	"./media/concrete03.jpg",
};

CRenderer*				CRenderer::m_ptrInstance = NULL;
static CEventReceiver*	t_ptrEventReceiver		 = NULL;

CRenderer::CRenderer()
{
	m_bFlagCreate		= false;
	m_ptrSelectedNode	= NULL;
	m_ptrPrevNode		= NULL;
	m_selectedId		= -1;
	m_ptrRatingGUI		= NULL;
	m_ptrEmotionGUI		= NULL;
	m_ptrAvgEmoGraph	= NULL;
}

CRenderer::~CRenderer()
{
	if(m_bFlagCreate)
		Destroy();
}

int CRenderer::Create(unsigned int nWidth, unsigned int nHeight, 
					  unsigned int nFrameRate,
					  bool bUseShadow, bool bUseFog)
{
	if(m_bFlagCreate)
		return ALREADY_CREATE;

	m_ptrDevice = NULL;
	m_ptrDriver	= NULL;
	m_ptrSmgr	= NULL;

	t_ptrEventReceiver = new CEventReceiver;
	t_ptrEventReceiver->m_setDataPtr(&this->m_dataList);

	// initialize irrlicht engine
	m_ptrDevice = createDevice(EDT_OPENGL, dimension2d<u32>(nWidth, nHeight),
							   32, false, bUseShadow, false, t_ptrEventReceiver);

	if(!m_ptrDevice)
		return FAIL_CREATEDEV;

	//m_ptrDevice->setResizable(true);
	m_ptrDriver	= m_ptrDevice->getVideoDriver(); 
	m_ptrSmgr	= m_ptrDevice->getSceneManager(); 

	// shadow
	if(bUseShadow)
		m_ptrSmgr->setShadowColor(SColor(64, 0, 0, 0));


	m_ptrDriver->setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, true);

	// set frame rate
	m_nFrameRate = nFrameRate;
	m_minTime	 = 1000 / nFrameRate;

	IGUIEnvironment* ptrEnv = m_ptrDevice->getGUIEnvironment(); 
	IGUIFont*  font = ptrEnv->getFont("./media/fonts/arial10.xml");
	ptrEnv->getSkin()->setFont(font);
	ptrEnv->getSkin()->setColor(EGDC_BUTTON_TEXT, SColor(255, 255, 255, 255));

	m_ptrQueryEdit = ptrEnv->addEditBox(L"", rect<s32>(450, 620, 800, 640));
	m_ptrQueryEdit->setVisible(false);

	IGUICheckBox* ptrCheckBox;
	ptrCheckBox = ptrEnv->addCheckBox(true, rect<s32>(1000, 10, 1130, 30), 0, ACTION, L"Action & Adv");
	AddBox(vector3df(150, 100, 0), vector3df(3, 3, 3), SColor(255, 255, 0, 0));
	m_ptrCheckBoxList.push_back(ptrCheckBox);
	ptrCheckBox = ptrEnv->addCheckBox(true, rect<s32>(1150, 10, 1280, 30), 0, HORROR, L"Horror");
	m_ptrCheckBoxList.push_back(ptrCheckBox);
	ptrCheckBox = ptrEnv->addCheckBox(true, rect<s32>(1300, 10, 1400, 30), 0, CLASSIC, L"Classic");
	m_ptrCheckBoxList.push_back(ptrCheckBox);
	ptrCheckBox = ptrEnv->addCheckBox(true, rect<s32>(1450, 10, 1700, 30), 0, COMEDY, L"Comedy");
	m_ptrCheckBoxList.push_back(ptrCheckBox);
	ptrCheckBox = ptrEnv->addCheckBox(true, rect<s32>(1000, 40, 1130, 60), 0, DOCUMENTARIES, L"Documentaries");
	m_ptrCheckBoxList.push_back(ptrCheckBox);
	ptrCheckBox = ptrEnv->addCheckBox(true, rect<s32>(1150, 40, 1280, 60), 0, MUSIC, L"Music");
	m_ptrCheckBoxList.push_back(ptrCheckBox);
	ptrCheckBox = ptrEnv->addCheckBox(true, rect<s32>(1300, 40, 1700, 60), 0, KIDS, L"Kids");
	m_ptrCheckBoxList.push_back(ptrCheckBox);
	ptrCheckBox = ptrEnv->addCheckBox(true, rect<s32>(1450, 40, 1700, 60), 0, ROMANCE, L"Romance");
	m_ptrCheckBoxList.push_back(ptrCheckBox);
	ptrCheckBox = ptrEnv->addCheckBox(true, rect<s32>(1000, 70, 1130, 90), 0, TV_SHOWS, L"TV Shows");
	m_ptrCheckBoxList.push_back(ptrCheckBox);
	ptrCheckBox = ptrEnv->addCheckBox(true, rect<s32>(1150, 70, 1280, 90), 0, DRAMAS, L"Dramas");
	m_ptrCheckBoxList.push_back(ptrCheckBox);
	ptrCheckBox = ptrEnv->addCheckBox(true, rect<s32>(1300, 70, 1700, 90), 0, THRILLERS, L"Thrillers");
	m_ptrCheckBoxList.push_back(ptrCheckBox);

	ptrEnv->addStaticText(L"Rating Filter", rect<s32>(1250, 160, 1550, 185));
	IGUIScrollBar* m_ptrRatingFilterBar = ptrEnv->addScrollBar(true, rect<s32>(1250,185,1580,210));
	m_ptrRatingFilterBar->setID(1);
	m_ptrRatingFilterBar->setMax(5);
	m_ptrRatingFilterBar->setSmallStep(1);
	m_ptrRatingFilterBar->setLargeStep(1);

	ptrEnv->addStaticText(L"Filter Sentiments Shown", rect<s32>(1250, 100, 1550, 125));
	IGUIScrollBar* m_ptrSentimentFilterBar = ptrEnv->addScrollBar(true, rect<s32>(1250,125,1580,150));
	m_ptrSentimentFilterBar->setID(2);
	m_ptrRatingFilterBar->setMax(100);
	m_ptrRatingFilterBar->setSmallStep(1);
	m_ptrRatingFilterBar->setLargeStep(10);

	//IGUIStaticText* text = ptrEnv->addStaticText(L"Sentiment Bar", rect<s32>(1250, 300, 1550, 325));
	m_ptrPosSentimentDesc = ptrEnv->addStaticText(L"Positivity: ", rect<s32>(1300, 320, 1550, 345));
	m_ptrPosSentimentDesc->setVisible(false);
	m_ptrNegSentimentDesc = ptrEnv->addStaticText(L"Negativity: ", rect<s32>(1300, 360, 1550, 385));
	m_ptrNegSentimentDesc->setVisible(false);

	ISceneNode* sentimentBox = this->AddBox(vector3df(1250, 100,0), vector3df(50,20,1), SColor(255,255,255,255));
	
	m_ptrCodeBox = new CGUIEditBoxIRB(L"",
									true, true,
									ptrEnv, ptrEnv->getRootGUIElement(),
									-1,
									rect<s32>(1250, 600, 1580, 1100),
									m_ptrDevice);
	m_ptrCodeBox->clearKeywords();
	m_ptrCodeBox->setBackgroundColor(SColor(0, 0, 0, 0));
	m_ptrCodeBox->setDrawBorder(false);
	m_ptrCodeBox->setDisplayLineCount(false);
	
	m_ptrInfoBox = new CGUIEditBoxIRB(L"",
									true, true,
									ptrEnv, ptrEnv->getRootGUIElement(),
									-1,
									rect<s32>(50, 10, 800, 300),
									m_ptrDevice);
	m_ptrInfoBox->clearKeywords();
	m_ptrInfoBox->setBackgroundColor(SColor(0, 0, 0, 0));
	m_ptrInfoBox->setDrawBorder(false);
	m_ptrInfoBox->setDisplayLineCount(false);
	m_ptrInfoBox->setScrollViz(false);
	m_ptrInfoBox->setTextColor(SColor(255, 255, 255, 150));

	t_LoadAffect();

	m_bFlagCreate = true;

	return SUCCESS;
}

int CRenderer::Destroy()
{
	if(!m_bFlagCreate)
		return NOT_CREATE;

	SAFE_DELETE(t_ptrEventReceiver);

	if(m_ptrRatingGUI)	delete m_ptrRatingGUI;
	if(m_ptrEmotionGUI)	delete m_ptrEmotionGUI;

	m_bFlagCreate = false;

	return SUCCESS;
}

CRenderer* CRenderer::Instance()
{
	if(!m_ptrInstance)
		m_ptrInstance = new CRenderer;

	return m_ptrInstance;
}

int CRenderer::AddDefaultCamera()
{
	if(!m_bFlagCreate)
		return NOT_CREATE;

	ICameraSceneNode* ptrCamera = NULL;
	
	ptrCamera = m_ptrSmgr->addCameraSceneNode(0);
	ptrCamera->setPosition(vector3df(-50, 0, 400));
	ptrCamera->setTarget(vector3df(-50, 0, 0));
	//ptrCamera->setUpVector(vector3df(0, 1, 0));
	ptrCamera->setFOV(45 * DEGTORAD);
	m_aCamera[0] = ptrCamera;
	m_ptrSmgr->setActiveCamera(m_aCamera[0]);

	// rating
	m_ptrRatingGUI  = new CRatingGUI;
	m_ptrEmotionGUI = new CEmotionBar;
	m_ptrAvgEmoGraph = new CAvgEmoGraph;
	
	m_ptrSentimentBar = new SentimentBar(m_ptrPosSentimentDesc, m_ptrNegSentimentDesc);

	AddSphere("", -1, vector3df(-99, 160.5, 0), 1.5, SColor(180, 255, 50, 50));
	AddSphere("", -1, vector3df(-99, 152, 0), 1.5, SColor(180, 255, 150, 255));
	AddSphere("", -1, vector3df(-99, 143.5, 0), 1.5, SColor(180, 255, 200, 200));
	AddSphere("", -1, vector3df(-138, 160.5, 0), 1.5, SColor(180, 50, 255, 50));
	AddSphere("", -1, vector3df(-138, 152, 0), 1.5, SColor(180, 150, 255, 255));
	AddSphere("", -1, vector3df(-138, 143.5, 0), 1.5, SColor(180, 255, 255, 200));
	AddSphere("", -1, vector3df(-177, 160.5, 0), 1.5, SColor(180, 50, 50, 255));
	AddSphere("", -1, vector3df(-177, 152, 0), 1.5, SColor(180, 150, 50, 255));
	AddSphere("", -1, vector3df(-177, 143.5, 0), 1.5, SColor(180, 200, 200, 255));
	AddSphere("", -1, vector3df(-216, 160.5, 0), 1.5, SColor(180, 200, 255, 150));
	AddSphere("", -1, vector3df(-216, 152, 0), 1.5, SColor(180, 100, 100, 100));

	return SUCCESS;
}

int CRenderer::AddLight(vector3df pos, SColorf color, float radius)
{
	if(!m_bFlagCreate)
		return NOT_CREATE;

	ILightSceneNode* ptrLight = NULL;
	
	ptrLight = m_ptrSmgr->addLightSceneNode(0, pos, color, radius);

	if(!ptrLight)
		return FAIL_CREATENODE;

	return SUCCESS;
}

ISceneNode*  CRenderer::AddBox(vector3df pos, vector3df size, 
							   SColor color)
{
	if(!m_bFlagCreate)
		return NULL;

	// add a box
	IMeshSceneNode*			ptrSceneNode = NULL;

	ptrSceneNode = m_ptrSmgr->addCubeSceneNode(1, 0, -1, pos, vector3df(0, 0, 0), size);
	ptrSceneNode->setPosition(pos);
	ptrSceneNode->setMaterialFlag(EMF_NORMALIZE_NORMALS, true);
	ptrSceneNode->setMaterialTexture(0, AddTextureFromSColor(color, "box", 
									dimension2d<u32>(32, 32)));

	return ((ISceneNode*)ptrSceneNode);
}

ISceneNode* CRenderer::AddSphere(std::string name, int nId, vector3df pos, float radius, SColor color)
{
	if(!m_bFlagCreate)
		return NULL;

	// add a sphere
	IMeshSceneNode*			ptrSceneNode = NULL;
	gui::IGUIEnvironment*	ptrGUI		 = m_ptrDevice->getGUIEnvironment();
	wchar_t					aText[256];
	IGUIFont*				ptrFont  = ptrGUI->getFont("./media/fonts/arial10.xml");
	IGUIFont*				ptrFont2 = ptrGUI->getFont("./media/fonts/arial12.xml");

	ptrSceneNode = m_ptrSmgr->addSphereSceneNode(radius, 16, 0, -1, pos);
	ptrSceneNode->setName(name.c_str());
	ptrSceneNode->setMaterialFlag(EMF_NORMALIZE_NORMALS, true);
	ptrSceneNode->setMaterialTexture(0, AddTextureFromSColor(color, 
															 "sphere", 
															 dimension2d<u32>(32, 32)));

	t_ConvertC2W(name.c_str(), aText, name.size() + 1);

	ITextSceneNode* pTextNode = m_ptrSmgr->addTextSceneNode(ptrFont2, 
								aText, SColor(255, 255, 255, 255), ptrSceneNode, 
								vector3df(0, radius * 4.0f, 0));

	pTextNode->setVisible(false);
	pTextNode = m_ptrSmgr->addTextSceneNode(ptrFont, 
								aText, SColor(50, 255, 255, 255), ptrSceneNode, 
								vector3df(0, radius * 3.f, 0));
	pTextNode->setVisible(true);

	m_dataList[ptrSceneNode] = nId;

	std::cout << "Map size in renderer: " << m_dataList.size() << std::endl;

	return ((ISceneNode*)ptrSceneNode);
}

ISceneNode* CRenderer::AddText(std::string name, irr::core::vector3df pos, 
							   irr::video::SColor color, 
							   irr::scene::ISceneNode* ptrParent)
{
	if(!m_bFlagCreate)
		return NULL;

	gui::IGUIEnvironment*	ptrGUI		 = m_ptrDevice->getGUIEnvironment();
	ISceneNode*				ptrSceneNode = NULL;
	wchar_t					aText[256];

	t_ConvertC2W(name.c_str(), aText, name.size() + 1);

	ptrSceneNode = m_ptrSmgr->addTextSceneNode(ptrGUI->getBuiltInFont(), 
											   aText, color, ptrParent, pos);
	return ptrSceneNode;
}

IGUIStaticText*	CRenderer::AddStaticText(std::string name, irr::core::rect<s32> position, SColor color)
{
	wchar_t					aText[256];
	t_ConvertC2W(name.c_str(), aText, name.size() + 1);

	IGUIEnvironment* ptrEnv = m_ptrDevice->getGUIEnvironment();
	IGUIStaticText* textBox = ptrEnv->addStaticText(aText, position);
	return textBox;
}

int CRenderer::GetTime()
{
	if(!m_bFlagCreate)
		return 0;

	return (m_ptrDevice->getTimer()->getTime());
}

void CRenderer::SetSelectedNode(irr::scene::ISceneNode* ptrNode)
{
	m_ptrSelectedNode = ptrNode;

	UpdateSentimentBar();
}

void CRenderer::UpdateSentimentBar() {
	CDataMgr*	pDataMgr = CDataMgr::Instance();
	std::unordered_map<ISceneNode*, int> nodeMap = m_dataList;

	ISceneNode* selected = this->m_ptrSelectedNode;
	s32 id = selected->getID();
	std::string str = selected->getName();

	int movieId = m_dataList[selected];
	NetflixDataElement data;
	pDataMgr->GetData(movieId, data);

	float positivity;
	float negativity;
	data.getAvgSentimentFromComments(positivity, negativity);

	m_ptrSentimentBar->SetSentiment(positivity, negativity);
}

void CRenderer::UpdateQuery()
{
	stringc				text = m_ptrQueryEdit->getText();
	CDataMgr*			pDataMgr = CDataMgr::Instance();
	std::vector<std::pair<int, float> > result;
	std::stringstream	ss;
	NetflixDataElement	data;
	CWorld*				pWorld = CWorld::Instance();
	
	ss << text.c_str();

	result = pDataMgr->Query(ss.str());

	pWorld->ClearQueryResult();
	for(int i = 0; i < result.size(); i++)
	{
		pDataMgr->GetData(result[i].first, data);
		pWorld->QueryResult(data._title, result[i].second);
	}

	std::cout << "Result size : " << result.size() << "\n";
}

void CRenderer::AddSceneNode2Cat(CATEGORY category, irr::scene::ISceneNode* pNode)
{
	m_categoryList[(int)category].push_back(pNode);
}

void CRenderer::FlipVisible(CATEGORY category)
{
	std::vector<ISceneNode*> nodeList = m_categoryList[category];
	int						 nSize	  = nodeList.size();

	for(int i = 0; i < nSize; i++)
		nodeList[i]->setVisible(nodeList[i]->isVisible() ? false : true);
}

void CRenderer::FilterNodes(double minDisplay, int key) {
	CDataMgr*	pDataMgr = CDataMgr::Instance();
	std::unordered_map<ISceneNode*, int> nodeMap = m_dataList;

	if(key == 1) {
		m_minRatingVal = minDisplay;
	}
	else if(key == 2) {
		m_minSentimentVal = minDisplay;
	}
	else {
		return;
	}

	for(auto it = nodeMap.begin(); it != nodeMap.end(); ++it) {
		
		//Getting NetflixDataElem
		int movieId = it->second;
		NetflixDataElement dataElem;
		pDataMgr->GetData(movieId, dataElem);
		int netflixRating = dataElem._netflixRating;

		float positivity;
		float negativity;
		dataElem.getAvgSentimentFromComments(positivity, negativity);
		float sentiment = positivity;
		bool withinRange = (netflixRating >= m_minRatingVal) &&
							(sentiment >= m_minSentimentVal);

		ISceneNode* node = it->first;
		if(node->isTrulyVisible() && !withinRange) {
			node->setVisible(false);
		}
		else if(!node->isTrulyVisible() && withinRange) {
			node->setVisible(true);
		}
	}
}

void CRenderer::Step()
{
	static unsigned short	oldTime = 0;
	unsigned short			curTime = CUtility::MilliSec();
	int						nFps	= 0;
	stringw					str		= L"Visualizer - ";

	if(abs(curTime - oldTime) > m_minTime)
	{
		if(m_ptrDevice->run() && m_ptrDriver)
		{
			t_Render();

			oldTime = curTime;

			nFps = m_ptrDriver->getFPS();
			str += "[FPS:";
			str += nFps;
			str += "]";

			m_ptrDevice->setWindowCaption(str.c_str());
			m_ptrSmgr->setActiveCamera(m_aCamera[0]);
		}
	}
	else
		m_ptrDevice->yield();
}

void CRenderer::m_SetMat(SMaterial& mat, SColor color)
{
	mat.AmbientColor	= color;
	mat.DiffuseColor	= color;
	mat.FogEnable		= true;
}

void CRenderer::t_ConvertC2W(const char* ptrSrc, wchar_t* ptrDes, int nSize)
{
	int nCnt;

	for(nCnt = 0; nCnt < nSize; nCnt++)
		ptrDes[nCnt] = (wchar_t)ptrSrc[nCnt];
}

ITexture* CRenderer::AddTextureFromSColor(SColor& color, c8* name, dimension2d<u32>& size) 
{ 
	ITexture* texture = m_ptrDriver->addTexture(size, name, ECF_A8R8G8B8); 

	u32* p = (u32*)texture->lock(); 

	// Now use that pointer to acces array 
	for(s32 i=0; i < texture->getSize().Width * texture->getSize().Height; i++) 
		p[i] = color.color; // color member is the color in A8R8G8B8 Format 

	texture->unlock(); 

	return texture; 
}

void CRenderer::t_Render()
{
	CDataMgr*	pDataMgr = CDataMgr::Instance();
	int			aRating[10] = {0};

	m_ptrDriver->beginScene(true, true, SColor(255, 40, 40, 40));
	m_ptrSmgr->drawAll();

	// selected node
	if(m_ptrSelectedNode)
	{
		aabbox3df					boundingBox = m_ptrSelectedNode->getBoundingBox();
		CAttribute					attr(m_ptrSelectedNode->getName(), "_");
		std::vector<std::string>	nameList = attr.List();
		list<ISceneNode*>			children = m_ptrSelectedNode->getChildren();

		if(children.size() > 0 && nameList.size() != 2)
		{
			ITextSceneNode* pNode = (ITextSceneNode*)(*(children.begin()));
			pNode->setVisible(true);
			pNode = (ITextSceneNode*)(*(children.getLast()));
			pNode->setVisible(false);

			if(m_ptrPrevNode && m_ptrPrevNode != m_ptrSelectedNode &&
				m_ptrPrevNode->getChildren().getSize() > 0)
			{
				list<ISceneNode*> prevChild = m_ptrPrevNode->getChildren();
				ITextSceneNode* pPrevNode = (ITextSceneNode*)(*(prevChild.begin()));
				pPrevNode->setVisible(false);
				pPrevNode = (ITextSceneNode*)(*(prevChild.getLast()));
				pPrevNode->setVisible(true);
			}
			t_UpdateInfo(m_dataList[m_ptrSelectedNode]);
			m_ptrPrevNode = m_ptrSelectedNode;
		}

		if(strcmp(m_ptrSelectedNode->getName(), "Query Sphere") == 0)
		{
			m_ptrInfoBox->setText(L"");
			m_ptrCodeBox->setText(L"");
			m_ptrEmotionGUI->SetEmotions(std::vector<float>());
			m_ptrQueryEdit->setVisible(true);
			m_ptrDevice->getGUIEnvironment()->setFocus(m_ptrQueryEdit);
			m_ptrSentimentBar->SetVisible(false);
		}
		else
		{
			if(nameList.size() == 2 && m_selectedId != -1)
			{
				int index = m_ptrRatingGUI->Index(m_ptrSelectedNode->getName());

				NetflixDataElement	data;
				wchar_t				aText[4096];

				pDataMgr->GetData(m_selectedId, data);
				t_ConvertC2W(data._userComments[index].Comment().c_str(), 
							 aText, 
							 data._userComments[index].Comment().size() + 1);
				m_ptrCodeBox->setText(aText);
				m_ptrEmotionGUI->SetEmotions(data._userComments[index].Emotions());
				//m_ptrSentimentBar->SetSentiment(data.getAvgSentimentFromComments());
			}
			else
			{
				m_ptrQueryEdit->setVisible(false);
			}
		}
	}
	m_ptrSmgr->drawAll();
	m_ptrDevice->getGUIEnvironment()->drawAll();
	m_ptrDriver->endScene();
}

void CRenderer::t_UpdateInfo(int nId)
{
	NetflixDataElement	data;
	CDataMgr*			pDataMgr = CDataMgr::Instance();
	std::stringstream	ss;
	wchar_t				aText[2048];

	pDataMgr->GetData(nId, data);

	ss << "Title : " << data._title << "\nGenre : " << data._mainGenre 
	   << "\nDirector : ";

	for(int i = 0; i < data._directors.size(); i++)
	{
		ss << data._directors[i];
		if(i < data._directors.size() - 1)
			ss << " / ";
	}

	ss << "\nCast : ";

	for(int i = 0; i < data._cast.size(); i++)
	{
		ss << data._cast[i];
		if(i < data._cast.size() - 1)
			ss << " / ";
	}

	t_ConvertC2W(ss.str().c_str(), aText, ss.str().size() + 1);

	m_ptrInfoBox->setText(aText);

	// update data to gui
	m_selectedId = nId;

	//HERE
	m_ptrRatingGUI->Reset();
	for(int i = 0; i < data._userComments.size(); i++) {
		UserComment comment = data._userComments[i];
		m_ptrRatingGUI->SetRating(i, (int)(data._userComments[i].Rating()), 
								  data._userComments[i].AvgEmotion());
		m_ptrRatingGUI->SetNumComments(i, (int)(data._userComments[i].Rating()), comment.Emotions().size());
	}

	m_ptrRatingGUI->Update();
	m_ptrSentimentBar->Update();
}

void CRenderer::DrawCircle(vector3df center, f32 radius, u32 vertexcount, 
						  vector3df normal, SColor color)
{
	// We want the vertex count to reflect a polygon
	if (vertexcount < 3) vertexcount = 3;
	if (vertexcount > 10000) vertexcount = 10000;


	core::array<video::S3DVertex> lstVertices(vertexcount+1);
	lstVertices.set_used(vertexcount+1);
	core::array<u16> lstIndices(vertexcount*2);
	lstIndices.set_used(vertexcount*2);

	normal.normalize();

	//Here we find the intersection of a plane whos normal is our normal vector,
	//with a sphere with radius 'radius'.

	//The equation of this circle is P + sV1 + tV2
	//where v1 id (0, c, -b) and v2 is (c, 0, -a), we need at least one nonzero one.
	core::vector3df v1 = core::vector3df(0, normal.Z, -normal.Y);
	core::vector3df v2 = core::vector3df(normal.Z, 0, -normal.X);

	if(v1 != core::vector3df(0,0,0))
	{	
		v1 = v1 / sqrt(1 - (normal.X * normal.X));
		v2 = v1.crossProduct(normal);
	}
	else
	{
		v2 = v2 / sqrt(1 - (normal.Y * normal.Y));
		v1 = v2.crossProduct(normal);
	}

	const f32 angle = 2*core::PI/vertexcount;

	video::S3DVertex vert;
	vert.Color = color;         // Always the same color: don't set it every time new

	vert.Pos = center + radius * v1;        // Set position for first vertex

	lstVertices[0] = vert;      // Set first vertex

	for(u32 x = 0; x < vertexcount; ++x)
	{
		// Position of start vertex = position of end vertex
		lstIndices[2*x] = x;

		const f32 angle_mul_xp1 = angle * (x + 1);
		vert.Pos = center + radius * ( cos(angle_mul_xp1) * v1 + sin(angle_mul_xp1) * v2 );
		lstIndices[2*x+1] = x+1;
		lstVertices[x+1] = vert;
	}

	// render
	m_ptrDriver->drawVertexPrimitiveList(&lstVertices[0], vertexcount+1, &lstIndices[0], vertexcount, video::EVT_STANDARD, scene::EPT_LINES, video::EIT_16BIT);
}

void CRenderer::t_LoadAffect()
{
	CFileIO		file;
	char		szBuffer[1024];

	file.Create("emotion/adjectives.dat");

	while(file.ReadLine(szBuffer))
	{
		CAttribute		attr(szBuffer, " \t\n");
		std::vector<std::string>	list = attr.List();

		if(list[0].find("sad") != list[0].npos)
		{
			int a;

			a = 0;
		}
			
		for(int i = 1; i < list.size(); i++)
		{
			if(StringTo<float>(list[i]) > 0)
			{
				if(i == 5 || i == 6 || i == 9)
				{
					m_ptrCodeBox->addKeyword(list[0].c_str(), SColor(255, 255, 100, 100), true);
					break;
				}
				else
				{
					m_ptrCodeBox->addKeyword(list[0].c_str(), SColor(255, 100, 100, 255), true);
					break;
				}
			}
		}
	}

	file.Destroy();

	file.Create("emotion/adverbs.dat");

	while(file.ReadLine(szBuffer))
	{
		CAttribute		attr(szBuffer, " \t\n");
		std::vector<std::string>	list = attr.List();

		for(int i = 1; i < list.size(); i++)
		{
			if(StringTo<float>(list[i]) > 0)
			{
				if(i == 5 || i == 6 || i == 9)
				{
					m_ptrCodeBox->addKeyword(list[0].c_str(), SColor(255, 255, 100, 100), true);
					break;
				}
				else
				{
					m_ptrCodeBox->addKeyword(list[0].c_str(), SColor(255, 100, 100, 255), true);
					break;
				}
			}
		}
	}

	file.Destroy();

	file.Create("emotion/nouns.dat");

	while(file.ReadLine(szBuffer))
	{
		CAttribute		attr(szBuffer, " \t\n");
		std::vector<std::string>	list = attr.List();

		for(int i = 1; i < list.size(); i++)
		{
			if(StringTo<float>(list[i]) > 0)
			{
				if(i == 5 || i == 6 || i == 9)
				{
					m_ptrCodeBox->addKeyword(list[0].c_str(), SColor(255, 255, 100, 100), true);
					break;
				}
				else
				{
					m_ptrCodeBox->addKeyword(list[0].c_str(), SColor(255, 100, 100, 255), true);
					break;
				}
			}
		}
	}

	file.Destroy();

	file.Create("emotion/verbs.dat");

	while(file.ReadLine(szBuffer))
	{
		CAttribute		attr(szBuffer, " \t\n");
		std::vector<std::string>	list = attr.List();
		
		for(int i = 1; i < list.size(); i++)
		{
			if(StringTo<float>(list[i]) > 0)
			{
				if(i == 5 || i == 6 || i == 9)
				{
					m_ptrCodeBox->addKeyword(list[0].c_str(), SColor(255, 255, 100, 100), true);
					break;
				}
				else
				{
					m_ptrCodeBox->addKeyword(list[0].c_str(), SColor(255, 100, 100, 255), true);
					break;
				}
			}
		}
	}

	file.Destroy();

}


